.model tiny

.data
Msg_new_line:	db 0dh, 0ah, '$'
Msg_error:	db 'An error occurred!$'
Msg_enter_numb:	db 'Enter the number: $'
Msg_your_numb:	db 'Your number is: $'
Msg_chz_in:	db 'Please, enter the input numeric system (b/d/h): $'
Msg_chz_out:	db 'Please, enter the output numeric system (b/d/h): $'

.code

org 100h

jumps

Start:	xor ax, ax
	xor bx, bx
	xor cx, cx
	xor dx, dx
	
CHZ_IN:	mov ah, 9h
	mov dx, offset Msg_new_line
	int 21h
	
	mov ah, 9h
	mov dx, offset Msg_chz_in
	int 21h
	
	mov ah, 0h	; keyboard input: scan code in ah, ASCII in al
	int 16h
		
	mov ah, 0eh	; in al character to write
	int 10h
	
	cmp al, 42h
	jz Input2
	cmp al, 62h
	jz Input2
	
	cmp al, 44h
	jz Input10
	cmp al, 64h
	jz Input10
	
	cmp al, 48h
	jz Input16
	cmp al, 68h
	jz Input16
	
	mov ah, 09h
	mov dx, offset Msg_new_line
	int 21h
	
	mov ah, 09h
	mov dx, offset Msg_error
	int 21h
	
	jmp CHZ_IN	
	
Input2:	mov ah, 9h
	mov dx, offset Msg_new_line
	int 21h

	mov ah, 9h
	mov dx, offset Msg_enter_numb
	int 21h
	
In2next:mov ah, 0h
	int 16h
	
	cmp ah, 1ch
	jz CHZ_OUT
	
	mov ah, 0eh
	int 10h
	
	shl bx, 1
	xor ah, ah	;
	sub al, 30h	; make digit from ASCII character
	or bx, ax
	
	jmp In2next
	
Input10:mov ah, 9h
	mov dx, offset Msg_new_line
	int 21h
	
	mov ah, 9h
	mov dx, offset Msg_enter_numb
	int 21h

In10next: mov ah, 0h
	int 16h
	
	cmp ah, 1ch
	jz CHZ_OUT
	
	mov ah, 0eh
	int 10h
	
	sub al, 30h
	xor ah, ah
	
	xchg ax, bx	; only for (bx * 10)
	mov dx, 0ah
	mul dx
	xchg ax, bx
	
	add bx, ax
	
	jmp In10next	
	
Input16:mov ah, 9h
	mov dx, offset Msg_new_line
	int 21h
	
	mov ah, 9h
	mov dx, offset Msg_enter_numb
	int 21h

In16next: mov ah, 0h
	int 16h

	cmp ah, 1ch
	jz CHZ_OUT
	
	mov ah, 0eh
	int 10h
	
	cmp al, 3ah
	jb In123
	
	cmp al, 47h
	jb InCapABC
	
	cmp al, 67h
	jb Inabc
	
	jmp In16next
	
InCapABC: sub al, 37h
	jmp Contin16

Inabc:	sub al, 57h
	jmp Contin16

In123:	sub al, 30h
	
Contin16: xor ah, ah
	
	xchg ax, bx
	mov dx, 10h
	mul dx
	xchg ax, bx
	
	add bx, ax
	
	jmp In16Next
	
CHZ_OUT:mov ah, 9h
	mov dx, offset Msg_new_line
	int 21h
	
	mov ah, 9h
	mov dx, offset Msg_chz_out
	int 21h
	
	mov ah, 0h
	int 16h

	mov ah, 0eh
	int 10h
	
	cmp al, 42h
	jz Bin
	cmp al, 62h
	jz Bin
	
	cmp al, 44h
	jz Decim
	cmp al, 64h
	jz Decim
	
	cmp al, 48h
	jz Hex
	cmp al, 68h
	jz Hex
	
	mov ah, 9h
	mov dx, offset Msg_new_line
	int 21h
	
	mov ah, 9h
	mov dx, offset Msg_error
	int 21h
	
	jmp CHZ_OUT

	; convert to binary numeral system
Bin:	mov ah, 9h
	mov dx, offset Msg_new_line
	int 21h
	
	mov ah, 09h
	mov dx, offset Msg_your_numb
	int 21h
	
	mov cl, 0fh	; set the counter
	mov dx, 0ffffh	; set the mask
	
Conv2:	test dx, dx
	je Exit
	
	mov ax, bx	; copy
	shr ax, cl	; choose digits from the beginning
	add al, 30h	; conv to ASCII
	jmp Print	

Next2:	dec cl		; count--
	shr dx, 1h	; mask >> 1
	
	and bx, dx	; del 1st digit
	
	jmp Conv2

	; convert to heximal numeral system
Hex:	mov ah, 9h
	mov dx, offset Msg_new_line
	int 21h
	
	mov ah, 09h
	mov dx, offset Msg_your_numb
	int 21h
	
	xor si, si	; zero flag for LEAD_0
	mov cl, 0ch	; set the step of shifting
	mov dx, 0ffffh	; set the mask
	
Conv16:	test dx, dx
	je Exit
	
	mov ax, bx	; copy
	shr ax, cl
	
	cmp ax, 0ah	; convert to ASCII
	jae THEABC

THE123:	test si, si
	jz LEAD_0
	
	add ax, 30h
	jmp Print

THEABC:	add ax, 37h
	mov si, 1h	; every time mov =(
	jmp Print

Next16:	sub cl, 4h	; dec the step
	shr dx, 4h	; dec the mask
	and bx, dx
	
	jmp Conv16

	; convert to decimal numeral system
Decim:	mov ah, 9h
	mov dx, offset Msg_new_line
	int 21h
	
	mov ah, 09h
	mov dx, offset Msg_your_numb
	int 21h
	
	mov ax, bx	; copy
	xor dx, dx
	mov bx, 2710h	; 10000d - divider
	mov cx, 0ah	; 10d - divider for divider
	
	xor si, si	; for leading zeros flag
	
Conv10:	test bx, bx
	je Exit
	
	div bx		; ax - divident, dx - quotient
	
	test si, si
	jz LEAD_0
		
	add al, 30h
	jmp Print
	
Next10: ; I need to divide the divider (now in bx) but 'div' uses ax and dx,
	; in dx I now have my number w/o 1st digit,
	; so I need to save it
	; and finally place number in ax, divider in bx
	
	mov ax, bx	; move divider to use 'div'
	mov bx, dx	; to save quotient
	
	xor dx, dx	; delete trash
	div cx		; divide the divider, store it in ax
	mov dx, bx	; temporary move number in free register
	
	mov bx, ax	; move divided divider
	mov ax, dx	; restore the number
	
	xor dx, dx	; delete trash for further dividing
		
	jmp Conv10
		
LEAD_0:	test ax, ax
	jz Next10	; do not forget to change the label when changing the output system
	add ax, 30h
	mov si, 1h
	jmp Print

Print:	mov ah, 0eh
	int 10h
	jmp Next10	; do not forget to change the label when changing the output system
	
Exit:	mov ax, 4c00h
	int 21h
	
end	Start
